/*!
    \file    change log.txt
    \brief   change log for GD32E51x firmware

    \version 2026-02-09, V1.4.0, firmware for GD32E51x
*/

/*
    Copyright (c) 2024, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

******************* V1.4.0 2026-02-09 ******************************************************************************************
______________________Common______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Template/main.c
fix reason:
adapt misra +U

V1.3.0:
NONE
V1.4.0:
int value +U
_________________________________________________________________________________________________________________________________



______________________RTC____________________________________________________________________________________________

Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/PMU/Deepsleep_wakeup_RTC/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/PMU/Deepsleep_wakeup_exti/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/PMU/Standby_wakeup_RTC/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/PMU/Standby_wakeup_pin/main.c
fix reason:
切频补丁添加 
V1.3.0:
NONE
V1.4.0:
/* software delay to prevent the impact of Vcore fluctuations.
   It is strongly recommended to include it to avoid issues caused by self-removal. */
static void _soft_delay_(uint32_t time)
{
    __IO uint32_t i;
    for(i=0; i<time*10; i++){
    }
}


Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/BKP/Backup_data/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/BKP/Tamper/main.c
fix reason:
若RCU_BDCTL_BKPRST位置位时读BKP_DATAx，会导致MCU宕机/跑飞。需要在访问备份域内容之前先判断RCU_BDCTL_BKPRST位是否已清零，若置位则清除。
. 在访问备份域内容之前先判断RCU_BDCTL_BKPRST位是否已清零，若置位则清除

V1.3.0:
NONE
V1.4.0:
int main(void)
{
    /* led configuration and turn on all led */
    led_config();
    /* PMU lock enable */
    rcu_periph_clock_enable(RCU_PMU);
    /* BKP clock enable */
    rcu_periph_clock_enable(RCU_BKPI);
    /* enable write access to the registers in backup domain */
    pmu_backup_write_enable();
    /* confirm RCU_BDCTL_BKPRST bit is reset */
    if(RESET != (RCU_BDCTL & RCU_BDCTL_BKPRST)){
        rcu_bkp_reset_disable();
    }
__________________________________________________________________________________________________________________________

______________________USB____________________________________________________________________________________________

Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/USBD/dev_firmware_update/src/inter_flash_if.c
fix reason:
Programming and erasing instructions clear the flag bit

V1.3.0:
/*!
    \brief      erase flash sector
    \param[in]  addr: flash address to be erased
    \param[out] none
    \retval     MEM_OK if the operation is right, MEM_FAIL else
*/
static uint8_t flash_if_erase(uint32_t addr)
{
    fmc_unlock();
    
    fmc_page_erase(addr);

    return MEM_OK;
}
V1.4.0:
/*!
    \brief      erase flash sector
    \param[in]  addr: flash address to be erased
    \param[out] none
    \retval     MEM_OK if the operation is right, MEM_FAIL else
*/
static uint8_t flash_if_erase(uint32_t addr)
{
    fmc_unlock();

    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR);

    fmc_page_erase(addr);

    return MEM_OK;
}

Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/USBHS/usb_device/dev_firmware_update/src/inter_flash_if.c
fix reason:
The programming and erasing instructions add a clear flag bit


V1.3.0:
static uint8_t flash_if_erase(uint32_t addr)
{
    /* unlock the internal flash */
    fmc_unlock();


V1.4.0:
static uint8_t flash_if_erase(uint32_t addr)
{
    /* unlock the internal flash */
    fmc_unlock();

    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END);
    fmc_flag_clear(FMC_FLAG_WPERR);
    fmc_flag_clear(FMC_FLAG_PGAERR);
    fmc_flag_clear(FMC_FLAG_PGERR);
	
Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_usbd_library/class/device/printer/Source/printer_core.c
fix reason:
Modify the name of the string descriptor array of the device class


V1.3.0:
static uint8_t* usbd_msc_strings[] = 
{
    [STR_IDX_LANGID]  = (uint8_t *)&usbd_language_id_desc,
    [STR_IDX_MFC]     = (uint8_t *)&manufacturer_string,
    [STR_IDX_PRODUCT] = (uint8_t *)&product_string,
    [STR_IDX_SERIAL]  = (uint8_t *)&serial_string
};

usb_desc printer_desc = {
    .dev_desc    = (uint8_t *)&printer_dev_desc,
    .config_desc = (uint8_t *)&printer_config_desc,
    .strings     = usbd_msc_strings
};


V1.4.0:
static uint8_t* usbd_printer_strings[] = 
{
    [STR_IDX_LANGID]  = (uint8_t *)&usbd_language_id_desc,
    [STR_IDX_MFC]     = (uint8_t *)&manufacturer_string,
    [STR_IDX_PRODUCT] = (uint8_t *)&product_string,
    [STR_IDX_SERIAL]  = (uint8_t *)&serial_string
};

usb_desc printer_desc = {
    .dev_desc    = (uint8_t *)&printer_dev_desc,
    .config_desc = (uint8_t *)&printer_config_desc,
    .strings     = usbd_printer_strings
};

__________________________________________________________________________________________________________________________

______________________CAN____________________________________________________________________________________________

Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Source/gd32e51x_can.c
fix reason:
Fixed the bug of CAN message cancellation caused by IC design
.

V1.3.0:
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
{
    ErrStatus reval = SUCCESS;
    /* timeout for CAN_TSTAT_MSTx bits */
    uint32_t timeout = CAN_TIMEOUT;

    if(CAN_MAILBOX0 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS0 == (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        } else {
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
            while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
                reval = ERROR;
            }
        }
    } else if(CAN_MAILBOX1 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS1 == (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
            while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
                reval = ERROR;
            }
        }
        
V1.4.0:
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
{
    ErrStatus reval = SUCCESS;
    /* timeout for CAN_TSTAT_MSTx bits */
    uint32_t timeout = CAN_TIMEOUT;
    uint32_t reg_value0 = 0U;
    uint32_t reg_value1 = 0U;

    /* get the status of transmit FIFO order */
    reg_value0 = CAN_CTL(can_periph) & CAN_CTL_TFO;

    if(CAN_MAILBOX0 == mailbox_number) {
        reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY);
        if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS0 == reg_value1)){
            reval = ERROR;
        } else {
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
            while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
                reval = ERROR;
            }
        }
    } else if(CAN_MAILBOX1 == mailbox_number) {
        reg_value1 = CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY);
        if((CAN_CTL_TFO == reg_value0) && (CAN_TSTAT_TMLS1 == reg_value1)){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
            while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
                reval = ERROR;
            }
        }
        
__________________________________________________________________________________________________________________________

______________________ENET_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/ENET/Telnet/lwip-2.1.2
/fw3233/GD32E51x_Firmware_Library/Examples/ENET/Telnet/lwip-2.2.1
/fw3233/GD32E51x_Firmware_Library/Examples/ENET/Telnet/lwip-2.2.1/BUILDING
/fw3233/GD32E51x_Firmware_Library/Examples/ENET/Telnet/lwip-2.2.1/CHANGELOG
/fw3233/GD32E51x_Firmware_Library/Examples/ENET/Telnet/lwip-2.2.1/CMakeLists.txt
fix reason: 
upgrade lwip version to 2.2.1.

V1.2.0:


V1.3.0:






__________________________________________________________________________________________________________________________


______________________RCU_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Include/gd32e51x_rcu.h
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Source/gd32e51x_rcu.c
fix reason: 
HD add PLLSCTL register. add rcu_spread_spectrum_config/rcu_spread_spectrum_enable/rcu_spread_spectrum_disable function


V1.3.0:
NONE
V1.4.0:
    \brief    configure the spread spectrum modulation for the main PLL clock
    \param[in]  spread_spectrum_type: PLL spread spectrum modulation type select
      \arg        RCU_SS_TYPE_CENTER: center spread type is selected
      \arg        RCU_SS_TYPE_DOWN: down spread type is selected
    \param[in]  modstep: configure PLL spread spectrum modulation profile amplitude and frequency
      \arg        This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1
    \param[in]  modcnt: configure PLL spread spectrum modulation profile amplitude and frequency
      \arg        This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT <=2^15-1
    \param[out] none
    \retval     none
*/
void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, uint32_t modcnt)
{
    uint32_t reg;

    reg = RCU_PLLSSCTL;
    /* reset the RCU_PLLSSCTL register bits */
    reg &= ~(RCU_PLLSSCTL_MODCNT | RCU_PLLSSCTL_MODSTEP | RCU_PLLSSCTL_SS_TYPE);
    RCU_PLLSSCTL = (reg | spread_spectrum_type | modstep << 13 | modcnt);
}

/*!
    \brief    enable the PLL spread spectrum modulation
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rcu_spread_spectrum_enable(void)
{
    RCU_PLLSSCTL |= RCU_PLLSSCTL_SSCGON;
}

/*!
    \brief    disable the PLL spread spectrum modulation
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rcu_spread_spectrum_disable(void)
{
    RCU_PLLSSCTL &= ~RCU_PLLSSCTL_SSCGON;
}



__________________________________________________________________________________________________________________________

______________________SPI_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Source/gd32e51x_spi.c
fix reason: 
spi.c 中spi_quad_output_enable改为spi_quad_io23_output_enable,与spi.h中声明一致

V1.3.0:

V1.4.0:


__________________________________________________________________________________________________________________________

______________________TIMER_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Source/gd32e51x_timer.c
fix reason: 
修复SWITCH函数问题

V1.3.0:
    case TIMER13:
        /* reset TIMER13 */
        rcu_periph_reset_enable(RCU_TIMER13RST);
        rcu_periph_reset_disable(RCU_TIMER13RST);
    case TIMER14:
        /* reset TIMER14 */
        rcu_periph_reset_enable(RCU_TIMER14RST);
        rcu_periph_reset_disable(RCU_TIMER14RST);
    case TIMER15:
        /* reset TIMER15 */
        rcu_periph_reset_enable(RCU_TIMER15RST);
        rcu_periph_reset_disable(RCU_TIMER15RST);
        break;
V1.4.0:
    case TIMER13:
        /* reset TIMER13 */
        rcu_periph_reset_enable(RCU_TIMER13RST);
        rcu_periph_reset_disable(RCU_TIMER13RST);
        break;
    case TIMER14:
        /* reset TIMER14 */
        rcu_periph_reset_enable(RCU_TIMER14RST);
        rcu_periph_reset_disable(RCU_TIMER14RST);
        break;
    case TIMER15:
        /* reset TIMER15 */
        rcu_periph_reset_enable(RCU_TIMER15RST);
        rcu_periph_reset_disable(RCU_TIMER15RST);
        break;

__________________________________________________________________________________________________________________________

______________________TIMER_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Firmware/GD32E51x_standard_peripheral/Source/gd32e51x_timer.c
fix reason: 
修复SWITCH函数问题

V1.3.0:
    case TIMER13:
        /* reset TIMER13 */
        rcu_periph_reset_enable(RCU_TIMER13RST);
        rcu_periph_reset_disable(RCU_TIMER13RST);
    case TIMER14:
        /* reset TIMER14 */
        rcu_periph_reset_enable(RCU_TIMER14RST);
        rcu_periph_reset_disable(RCU_TIMER14RST);
    case TIMER15:
        /* reset TIMER15 */
        rcu_periph_reset_enable(RCU_TIMER15RST);
        rcu_periph_reset_disable(RCU_TIMER15RST);
        break;
V1.4.0:
    case TIMER13:
        /* reset TIMER13 */
        rcu_periph_reset_enable(RCU_TIMER13RST);
        rcu_periph_reset_disable(RCU_TIMER13RST);
        break;
    case TIMER14:
        /* reset TIMER14 */
        rcu_periph_reset_enable(RCU_TIMER14RST);
        rcu_periph_reset_disable(RCU_TIMER14RST);
        break;
    case TIMER15:
        /* reset TIMER15 */
        rcu_periph_reset_enable(RCU_TIMER15RST);
        rcu_periph_reset_disable(RCU_TIMER15RST);
        break;

__________________________________________________________________________________________________________________________


______________________FMC_______________________________________________________________________________________________
Fix file:
/fw3233/GD32E51x_Firmware_Library/Examples/FMC/Erase_program/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/FMC/Security_protection/main.c
/fw3233/GD32E51x_Firmware_Library/Examples/FMC/Write_protection/main.c
fix reason: 
Clear the flag before operation to prevent the flag from being set due to other operations inserted by the customer, which may affect the next operation.
Modifying Content:Before operating (erasing/writing) flash and option bytes, add the operation to clear all flags.


V1.3.0:
int main(void)
{
    /* initialize leds on the board */
    gd_eval_led_init(LED2);
    gd_eval_led_init(LED3);
    /* unlock the flash program/erase controller */
    fmc_unlock();
    ob_unlock();

    fmc_flag_clear(FMC_FLAG_END);
    fmc_flag_clear(FMC_FLAG_WPERR);
    fmc_flag_clear(FMC_FLAG_PGAERR);
    fmc_flag_clear(FMC_FLAG_PGERR);
V1.4.0:
int main(void)
{
    /* initialize leds on the board */
    gd_eval_led_init(LED2);
    gd_eval_led_init(LED3);
    /* unlock the flash program/erase controller */
    fmc_unlock();
    ob_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_END);
    fmc_flag_clear(FMC_FLAG_WPERR);
    fmc_flag_clear(FMC_FLAG_PGAERR);
    fmc_flag_clear(FMC_FLAG_PGERR);

__________________________________________________________________________________________________________________________

